package com.agent.generator.service;

import com.agent.common.constant.CommonConstants;
import com.agent.common.exception.BusinessException;
import com.agent.common.result.ResultCode;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import software.amazon.awssdk.core.sync.RequestBody;
import software.amazon.awssdk.services.s3.S3Client;
import software.amazon.awssdk.services.s3.model.GetUrlRequest;
import software.amazon.awssdk.services.s3.model.PutObjectRequest;
import software.amazon.awssdk.services.s3.model.S3Exception;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URL;
import java.time.Duration;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.UUID;

/**
 * Cloudflare存储服务
 *
 * @author Jeff_Wan
 * @description 实现文件存储到Cloudflare R2
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class CloudflareStorageService {
    private final S3Client s3Client;
    private final String bucketName;

    /**
     * 存储文件到 Cloudflare R2
     *
     * @param file     上传的文件
     * @param userId   用户ID
     * @param fileType 文件类型(input/output)
     * @return 文件存储路径 (S3 key)
     */
    public String storeFile(MultipartFile file, Long userId, String fileType) {
        // 验证文件大小
        if (file.getSize() > CommonConstants.MAX_FILE_SIZE) {
            throw new BusinessException(ResultCode.FILE_UPLOAD_FAILED, "File size exceeds limit");
        }

        // 验证文件类型
        String originalFilename = file.getOriginalFilename();
        if (originalFilename == null) {
            throw new BusinessException(ResultCode.FILE_UPLOAD_FAILED, "Invalid file name");
        }

        String fileExtension = getFileExtension(originalFilename).toLowerCase();
        boolean supported = false;
        for (String type : CommonConstants.SUPPORTED_IMAGE_TYPES) {
            if (type.equalsIgnoreCase(fileExtension)) {
                supported = true;
                break;
            }
        }

        if (!supported) {
            throw new BusinessException(ResultCode.FILE_UPLOAD_FAILED, "Unsupported file type: " + fileExtension);
        }

        // 生成存储路径
        String dateDir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
        String fileName = UUID.randomUUID() + "." + fileExtension;
        String objectKey = String.format("CreateAlVideo/%s/%s/%s/%s",
                userId, fileType, dateDir, fileName);

        try {
            // 上传文件到 Cloudflare R2
            PutObjectRequest putRequest = PutObjectRequest.builder()
                    .bucket(bucketName)
                    .key(objectKey)
                    .contentType(getContentType(fileExtension))
                    .build();

            s3Client.putObject(putRequest, RequestBody.fromBytes(file.getBytes()));

            log.info("File uploaded to Cloudflare R2: {}", objectKey);
            return objectKey;
        } catch (S3Exception e) {
            log.error("Cloudflare R2 upload failed: {}", e.getMessage(), e);
            throw new BusinessException(ResultCode.FILE_UPLOAD_FAILED, "Cloudflare upload error");
        } catch (IOException e) {
            log.error("File read error: {}", e.getMessage(), e);
            throw new BusinessException(ResultCode.FILE_UPLOAD_FAILED, "File read error");
        }
    }

    /**
     * 下载并存储远程文件到 Cloudflare R2
     *
     * @param fileUrl  远程文件URL
     * @param userId   用户ID
     * @param fileType 文件类型
     * @param fileName 原始文件名
     * @return 文件存储路径 (S3 key)
     */
    public String downloadAndStoreFile(String fileUrl, Long userId, String fileType, String fileName) {
        try {
            // 获取文件内容
            byte[] fileContent = downloadFileFromUrl(fileUrl);

            // 获取文件扩展名
            String fileExtension = getFileExtensionFromUrl(fileUrl);
            if (fileExtension.isEmpty()) {
                fileExtension = getFileExtension(fileName);
            }

            // 生成存储路径
            String dateDir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            String uniqueFileName = UUID.randomUUID() + "." + fileExtension;
            String objectKey = String.format("CreateAlVideo/%s/%s/%s/%s",
                    userId, fileType, dateDir, uniqueFileName);

            // 上传到 Cloudflare R2
            PutObjectRequest putRequest = PutObjectRequest.builder()
                    .bucket(bucketName)
                    .key(objectKey)
                    .contentType(getContentType(fileExtension))
                    .build();

            s3Client.putObject(putRequest, RequestBody.fromBytes(fileContent));

            log.info("File downloaded and stored to Cloudflare R2: {}", objectKey);
            return objectKey;
        } catch (IOException e) {
            log.error("File download failed: {}", fileUrl, e);
            throw new BusinessException(ResultCode.FILE_UPLOAD_FAILED, "File download failed");
        } catch (S3Exception e) {
            log.error("Cloudflare R2 upload failed: {}", e.getMessage(), e);
            throw new BusinessException(ResultCode.FILE_UPLOAD_FAILED, "Cloudflare upload error");
        }
    }

    /**
     * 生成文件访问URL (预签名URL)
     *
     * @param objectKey 文件存储路径
     * @return 可访问的URL
     */
    public String generateFileUrl(String objectKey) {
        try {
            // Cloudflare R2 使用自定义域名访问
            return String.format("https://%s/%s", bucketName, objectKey);

            // 如果需要预签名URL（私有存储桶）
            // return generatePreSignedUrl(objectKey, Duration.ofDays(365))
        } catch (S3Exception e) {
            log.error("Failed to generate file URL: {}", e.getMessage(), e);
            return "";
        }
    }

    // 辅助方法
    private String getFileExtension(String filename) {
        int dotIndex = filename.lastIndexOf('.');
        if (dotIndex > 0 && dotIndex < filename.length() - 1) {
            return filename.substring(dotIndex + 1);
        }
        return "";
    }

    private String getFileExtensionFromUrl(String url) {
        int lastDot = url.lastIndexOf('.');
        int lastSlash = Math.max(url.lastIndexOf('/'), url.lastIndexOf('\\'));
        if (lastDot > lastSlash && lastDot < url.length() - 1) {
            return url.substring(lastDot + 1).toLowerCase();
        }
        return "";
    }

    private String getContentType(String fileExtension) {
        switch (fileExtension.toLowerCase()) {
            case "jpg":
            case "jpeg":
                return "image/jpeg";
            case "png":
                return "image/png";
            case "mp4":
                return "video/mp4";
            default:
                return "application/octet-stream";
        }
    }

    private byte[] downloadFileFromUrl(String fileUrl) throws IOException {
        try (InputStream in = new URL(fileUrl).openStream();
             ByteArrayOutputStream out = new ByteArrayOutputStream()) {

            byte[] buffer = new byte[4096];
            int bytesRead;

            while ((bytesRead = in.read(buffer)) != -1) {
                out.write(buffer, 0, bytesRead);
            }

            return out.toByteArray();
        }
    }

    /**
     * 流式传输大文件
     *
     * @param fileUrl  文件URL
     * @param userId   用户ID
     * @param fileType 文件类型
     * @param fileName 文件名
     * @return 存储路径
     */
    public String streamLargeFileToR2(String fileUrl, Long userId, String fileType, String fileName) {
        try (InputStream in = new URL(fileUrl).openStream()) {
            // 获取文件扩展名
            String fileExtension = getFileExtensionFromUrl(fileUrl);
            if (fileExtension.isEmpty()) {
                fileExtension = getFileExtension(fileName);
            }

            // 生成存储路径
            String dateDir = LocalDate.now().format(DateTimeFormatter.ofPattern("yyyyMMdd"));
            String uniqueFileName = UUID.randomUUID() + "." + fileExtension;
            String objectKey = String.format("CreateAlVideo/%s/%s/%s/%s",
                    userId, fileType, dateDir, uniqueFileName);

            // 流式上传到 Cloudflare R2
            PutObjectRequest putRequest = PutObjectRequest.builder()
                    .bucket(bucketName)
                    .key(objectKey)
                    .contentType(getContentType(fileExtension))
                    .build();

            // 使用流式上传
            s3Client.putObject(putRequest, RequestBody.fromInputStream(in, -1));

            return objectKey;
        } catch (IOException | S3Exception e) {
            log.error("Failed to stream file to R2", e);
            throw new BusinessException(ResultCode.FILE_UPLOAD_FAILED, "File streaming failed");
        }
    }

    /**
     * 预签名 URL 实现 (私有存储桶)
     *
     * @param objectKey
     * @param expiration
     * @return
     */
    public String generatePreSignedUrl(String objectKey, Duration expiration) {
        try {
            GetUrlRequest request = GetUrlRequest.builder()
                    .bucket(bucketName)
                    .key(objectKey)
                    .build();

            // 生成预签名URL
            URL url = s3Client.utilities().getUrl(request);

            // 添加过期时间参数（如果需要）
            return url + "?expires=" + (System.currentTimeMillis() + expiration.toMillis()) / 1000;
        } catch (S3Exception e) {
            log.error("Failed to generate presigned URL", e);
            return "";
        }
    }
}